package com.mdd.admin.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mdd.admin.service.ICouponService;
import com.mdd.admin.validate.commons.PageValidate;
import com.mdd.admin.validate.order.CouponCreateValidate;
import com.mdd.admin.validate.order.CouponIssuingValidate;
import com.mdd.admin.validate.order.CouponSearchValidate;
import com.mdd.admin.vo.coupon.CouponSettingVo;
import com.mdd.admin.vo.coupon.CouponVo;
import com.mdd.common.core.AjaxResult;
import com.mdd.common.core.PageResult;
import com.mdd.common.entity.coupon.Coupon;
import com.mdd.common.entity.coupon.CouponIssuing;
import com.mdd.common.entity.order.Order;
import com.mdd.common.entity.user.User;
import com.mdd.common.enums.CouponEnum;
import com.mdd.common.mapper.order.CouponIssuingMapper;
import com.mdd.common.mapper.order.CouponMapper;
import com.mdd.common.mapper.order.OrderMapper;
import com.mdd.common.mapper.user.UserMapper;
import com.mdd.common.util.*;
import com.mdd.common.vo.CouponConfigVo;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 优惠券服务
 *
 * @author shenjian
 * @createTime 2023年02月27日 22:10:00
 */
@Service
public class CouponServiceImpl implements ICouponService {

    @Resource
    private CouponMapper couponMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private CouponIssuingMapper couponIssuingMapper;

    @Override
    public List<CouponSettingVo> getConfig() {
        List<CouponSettingVo> couponList = new ArrayList<>();
        Map<String, String> couponMap = ConfigUtils.get("coupon");
        // 新用户注册
        String newUser = couponMap.get("new-user");
        // 邀请新人下单后
        String inviterOrder = couponMap.get("inviter-order");
        // 被邀请人下单后
        String inviteeOrder = couponMap.get("invitee-order");
        if (StringUtils.isNotBlank(newUser)) {
            CouponSettingVo settingVo = new CouponSettingVo();
            CouponConfigVo configVo = JSONObject.parseObject(newUser, CouponConfigVo.class);
            BeanUtils.copyProperties(configVo, settingVo);
            settingVo.setCouponAmount(AmountUtils.changeF2Y(configVo.getCouponAmount()));
            couponList.add(settingVo);
        }
        if (StringUtils.isNotBlank(inviterOrder)) {
            CouponSettingVo settingVo = new CouponSettingVo();
            CouponConfigVo configVo = JSONObject.parseObject(inviterOrder, CouponConfigVo.class);
            BeanUtils.copyProperties(configVo, settingVo);
            settingVo.setCouponAmount(AmountUtils.changeF2Y(configVo.getCouponAmount()));
            couponList.add(settingVo);
        }
        if (StringUtils.isNotBlank(inviteeOrder)) {
            CouponSettingVo settingVo = new CouponSettingVo();
            CouponConfigVo configVo = JSONObject.parseObject(inviteeOrder, CouponConfigVo.class);
            BeanUtils.copyProperties(configVo, settingVo);
            settingVo.setCouponAmount(AmountUtils.changeF2Y(configVo.getCouponAmount()));
            couponList.add(settingVo);
        }
        return couponList;
    }

    @Override
    public AjaxResult<Object> config(List<CouponSettingVo> couponList) {
        for (CouponSettingVo vo : couponList) {
            CouponConfigVo configVo = new CouponConfigVo();
            BeanUtils.copyProperties(vo, configVo);
            configVo.setCouponAmount(AmountUtils.changeY2F(vo.getCouponAmount()));
            switch (configVo.getType()) {
                case 1: {
                    if (StringUtils.isEmpty(configVo.getCouponName())) {
                        configVo.setCouponName("新用户注册");
                    }
                    ConfigUtils.set("coupon", "new-user", JSONObject.toJSONString(configVo));
                    break;
                }
                case 2: {
                    if (StringUtils.isEmpty(configVo.getCouponName())) {
                        configVo.setCouponName("邀请他人并下单");
                    }
                    ConfigUtils.set("coupon", "inviter-order", JSONObject.toJSONString(configVo));
                    break;
                }
                case 3: {
                    if (StringUtils.isEmpty(configVo.getCouponName())) {
                        configVo.setCouponName("新用户下单");
                    }
                    ConfigUtils.set("coupon", "invitee-order", JSONObject.toJSONString(configVo));
                    break;
                }
                default: {
                    return AjaxResult.failed(300, "类型出现问题");
                }
            }
        }
        return AjaxResult.success();
    }

    @Override
    public PageResult<CouponVo> list(PageValidate pageValidate, CouponSearchValidate searchValidate) {
        Integer pageNo = pageValidate.getPageNo();
        Integer pageSize = pageValidate.getPageSize();
        QueryWrapper<Coupon> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("id");

        couponMapper.setSearch(queryWrapper, searchValidate, new String[]{
                "=:type:str",
                "=:status:int",
                "=:user_id:int"
        });
        IPage<Coupon> iPage = this.couponMapper.selectPage(new Page<>(pageNo, pageSize), queryWrapper);
        // 用户IDS
        List<Integer> userIds = iPage.getRecords().stream()
                .map(Coupon::getUserId)
                .collect(Collectors.toList());
        List<Integer> couponIds = iPage.getRecords().stream().filter(coupon ->
                coupon.getStatus().equals(1))
                .map(Coupon::getId)
                .collect(Collectors.toList());
        List<Order> orders = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(couponIds)) {
            orders = orderMapper.selectList(new QueryWrapper<Order>()
                    .in("coupon_id", couponIds));
        }
        Map<Integer, List<Order>> orderMap = orders.stream().collect(Collectors.groupingBy(Order::getCouponId));
        List<CouponVo> list = new ArrayList<>(iPage.getRecords().size());
        if (CollectionUtils.isNotEmpty(userIds)) {
            Map<Integer, List<User>> map = userMapper.selectBatchIds(userIds)
                    .stream()
                    .collect(Collectors.groupingBy(User::getId));

            for (Coupon coupon : iPage.getRecords()) {
                CouponVo vo = new CouponVo();
                BeanUtils.copyProperties(coupon, vo);
                List<User> userList = map.get(coupon.getUserId());
                List<Order> orderList = orderMap.get(coupon.getId());
                if (CollectionUtils.isNotEmpty(userList)) {
                    vo.setUserId(userList.get(0).getSn());
                    vo.setUserName(userList.get(0).getNickname());
                    vo.setCouponAmount(AmountUtils.changeF2Y(coupon.getCouponAmount()));
                }
                if (CollectionUtils.isNotEmpty(orderList)) {
                    vo.setUseOrderNo(orderList.get(0).getOrderNo());
                }
                vo.setReleaseTimeStr(TimeUtils.timestampToDate(coupon.getReleaseTime()));
                vo.setUseTimeStr(TimeUtils.timestampToDate(coupon.getUseTime()));
                vo.setStartTimeStr(TimeUtils.timestampToDate(coupon.getStartTime()));
                vo.setEndTimeStr(TimeUtils.timestampToDate(coupon.getEndTime()));
                list.add(vo);
            }
        }
        return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), list);
    }

    @Override
    public int create(CouponCreateValidate createValidate) {
         // 根据用户编号查询用户ID
        User user = userMapper.selectOne(new QueryWrapper<User>()
                .eq("sn", createValidate.getUserId())
                .last("limit 1"));
        Assert.notNull(user, "用户编号不存在");

        Long now = TimeUtils.timestamp();
        Coupon coupon = new Coupon();
        coupon.setIssuingId(-1);
        coupon.setType(CouponEnum.BACKSTAGE_MANUAL.getKey());
        coupon.setUserId(user.getId());
        coupon.setCouponName(createValidate.getCouponName());
        coupon.setCouponAmount(AmountUtils.changeY2F(createValidate.getCouponAmount()));
        coupon.setSharer(0);
        coupon.setStatus(0);
        coupon.setThreshold(0);
        coupon.setReleaseTime(now);
        coupon.setStartTime(now);
        coupon.setEndTime(TimeUtils.calculateEndTime(now, createValidate.getValid()));
        return couponMapper.insert(coupon);
    }

    @Override
    public String issuing(CouponIssuingValidate issuingValidate) {
         // 生成随机串
        String sn = this.randomString();
        CouponIssuing couponIssuing = new CouponIssuing();
        couponIssuing.setSn(sn);
        couponIssuing.setCouponName("随机优惠券");
        couponIssuing.setCouponAmount(AmountUtils.changeY2F(issuingValidate.getAmount()));
        couponIssuing.setQuantity(issuingValidate.getQuantity());
        couponIssuing.setValidDate(1);
        couponIssuing.setThreshold(0);
        couponIssuing.setCreateTime(TimeUtils.timestamp());
        couponIssuingMapper.insert(couponIssuing);
        return sn;
    }

    private String randomString() {
        String random = ToolsUtils.randomString(15);
        Long count = couponIssuingMapper.selectCount(new QueryWrapper<CouponIssuing>()
                .eq("sn", random));
        if (count > 0) {
            return randomString();
        } else {
            return random;
        }
    }
}
